package com.atguigu.gmall.order.service;

import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.HttpClient;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.CartInfoMapper;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.rabbit.constant.MqConst;
import com.atguigu.gmall.rabbit.service.RabbitService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

@Service
public class OrderInfoServiceImpl implements OrderInfoService {

    @Value("${ware.url}")
    private String wareUrl;
    @Resource
    private ProductFeignClient productFeignClient;
    @Resource
    private OrderInfoMapper orderInfoMapper;
    @Resource
    private OrderDetailMapper orderDetailMapper;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private CartInfoMapper cartInfoMapper;
    @Resource
    private RabbitService rabbitService;

    //提交订单
    @Override
    public Long submitOrder(OrderInfo orderInfo) {
        //1、订单表 order-info      传入的参数不全，将剩余信息补全
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        StringBuilder sb = new StringBuilder();
        //防止金额被篡改，重新查询
        orderDetailList.forEach(orderDetail -> {
            //金额
            BigDecimal price = productFeignClient.getPrice(orderDetail.getSkuId());
            orderDetail.setOrderPrice(price);
            //订单描述
            sb.append(orderDetail.getSkuName() + " ");
        });
        //1.1、总金额    重新计算
        orderInfo.sumTotalAmount();//方法中将计算结果放回当前对象的totalAmount中
        //1.2、订单状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //1.3、订单描述      对拼接过长的订单描述进行截取
        if (sb != null && sb.length() > 100) {
            orderInfo.setTradeBody(sb.toString().substring(0, 100));
        } else {
            orderInfo.setTradeBody(sb.toString());
        }
        //1.4、订单交易编号（第三方支付用)    唯一：支付单位 + 精确到毫秒 + 1000内的随机数
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis() + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //1.5、创建时间
        Calendar calendar = Calendar.getInstance();//创建时间
        orderInfo.setCreateTime(calendar.getTime());
        //1.6、失效时间
        calendar.add(Calendar.MINUTE, 30);//加时间  单位，计数
        orderInfo.setExpireTime(calendar.getTime());
        //1.7、进度状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        //1.8、图片路径
        orderInfoMapper.insert(orderInfo);

        //2、订单详情表   order-detail
        //order-info表修改后数据库返回订单编号即id，之前为空，所以需要重新获取
        List<OrderDetail> orderDetailList1 = orderInfo.getOrderDetailList();
        //获取商品所有id，为删除缓存中的hash类型的cartinfo
        List<String> skuIds = new ArrayList<>();
        orderDetailList1.forEach(orderDetail -> {
            //订单表的主键
            orderDetail.setOrderId(orderInfo.getId());
            skuIds.add(orderDetail.getSkuId().toString());
            orderDetailMapper.insert(orderDetail);
        });
        //删除缓存中的购物车中已结算部分
        redisTemplate.opsForHash().delete(getCacheH(Long.parseLong("3")), skuIds.toArray());
        //删除DB中的购物车中已结算部分
        cartInfoMapper.delete(new QueryWrapper<CartInfo>()
                .eq("user_id", 3)
                .eq("is_checked", CartInfo.ISCHECKED));


        // 取消订单   ： 提交订单开始计时 30分钟后 如果用户不支付 取消订单
        // 12306 买票  30分钟    锁定的时间
        // 查询历史订单  取消   支付 未支付
        // 定时器 （下下策）
        // （上上策）  MQ  延迟消息  30分钟之后马上发消息  执行订单的取消

        //基于插件取消订单      更改订单状态，需要订单id
        rabbitService.sendDelayMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,
                MqConst.ROUTING_ORDER_CANCEL,
                orderInfo.getId(),
                MqConst.DELAY_TIME);

        return orderInfo.getId();
    }

    @Override
    public boolean hasStock(Long skuId, Integer skuNum) {
        //访问库存系统的地址
        String url = wareUrl + "/hasStock?skuId=" + skuId + "&num=" + skuNum;
        return "1".equals(HttpClientUtil.doGet(url));
    }

    @Override
    public void cancelOrder(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if (orderInfo != null) {//订单id可能为空，所有均需判断
            //未支付
            if (orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.name())){
                //未支付更新为已关闭
                orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
                //进度状态已关闭
                orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
                //更新订单
                orderInfoMapper.updateById(orderInfo);
                System.out.println("取消订单成功："+new Date());
            }
        }

    }

    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        return orderInfoMapper.selectById(orderId);
    }

    private String getCacheH(Long userId) {
        return RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    }
}
